/* 
 * Autores:
 *      Jonathan Lopez  11106
 *      Jorge Martínez  11237
 * 
 * Ultima revision: $Rev: 28 $
 *      Fecha: $Date: 2011-11-13 08:23:56 +0000 (Sun, 13 Nov 2011) $
 * 
 * Archivo: ProveedorDatosCSV.java
 */

package Datos.CSV;

import Servicios.Usuario;
import Servicios.iServidor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

/**
 * Provee datos desde una base de datos CSV.
 * 
 * @author Jorge
 * @author Jonathan
 */
public class ProveedorDatosCSV implements Servicios.Datos{
    final private ArchivoCSV usuarios, datos;
    
    private final int idxNombres_Usuario = 0;
    private final int idxApellidos_Usuario = 1;
    private final int idxUsuario_Usuario = 2;
    private final int idxContrasena_Usuario = 3;
    
    private final boolean encriptar = true;
    
    private static HashMap<String, ArrayList<String>> categoriasDefault =
            new HashMap<String, ArrayList<String>>();

    /**
     * Consructor, trata de abrir los archivos de usuarios y datos. Si estos
     * no existen entonces son creados.
     * @param archivoUsuarios Ruta del archivo .csv que contiene los datos
     * de usuarios.
     * @param archivoDatos Ruta del archivo .csv que contiene los datos de
     * servicios.
     * @throws IOException Esta excepcion es creada cuando alguno de los dos
     * archivos no existe y no se puede crear.
     */
    public ProveedorDatosCSV( String archivoUsuarios, String archivoDatos ) throws IOException {
        // Trata de abrir el archivo de usuarios, si no existe crea uno nuevo.
        ArchivoCSV tempUsuarios = new ArchivoCSV( archivoUsuarios, encriptar );
        if( !tempUsuarios.esValido() )
            tempUsuarios = new ArchivoCSV( "usuarios.csv",
                    new String[]{"nombres", "apellidos", "usuario", "contraseña"}, encriptar);
        
        // Trata de abrir el archivo de datos, si no existe crea uno nuevo.
        ArchivoCSV tempDatos = new ArchivoCSV( archivoDatos, encriptar );
        if( !tempDatos.esValido() )
            tempDatos = new ArchivoCSV( "datos.csv", ConstantesCSV.nombreCampos, encriptar );
        
        // Valida ambos archivos
        if( !tempUsuarios.esValido() || !tempDatos.esValido() )
            throw new java.io.IOException( "No se pueden crear los archivos de datos");
        else{
            usuarios = tempUsuarios;
            datos = tempDatos;
        }
         
        // Lee el archivo de categorias
        ArchivoCSV categorias = new ArchivoCSV( "ServiciosPredeterminados.csv", false );
        if( !categorias.esValido() )
            return;
        
        for (int i = 0; i < categorias.obtenerCantidadLineas(); i++) {
            String[] lineaActual = categorias.obtenerLinea(i);
            if( categoriasDefault.containsKey(lineaActual[0]) ){
                categoriasDefault.get(lineaActual[0]).add(lineaActual[1]);
            } else {
                ArrayList<String> arreglo = new ArrayList<String>();
                arreglo.add(lineaActual[1]);
                
                categoriasDefault.put(lineaActual[0], arreglo);
            }
        }
    }
    
    static HashMap<String, ArrayList<String>> obtenerCategoriasDefault(){
        return categoriasDefault;
    }
    
    /**
     * @see Servicios.Datos#agregarCategoria(Servicios.Usuario, java.lang.String) 
     */
    @Override
    public iServidor agregarCategoria(Usuario usuario, String nombreCategoria) {
        // Validar
        if( !validarUsuario(usuario) )
            return null;
        
        // Revisar si la categoria ya existe
        iServidor[] categoriasExistentes = obtenerCategorias(usuario);
        for (iServidor categoria : categoriasExistentes) {
            if( categoria.obtenerNombreCategoria().equals(nombreCategoria) )
                return null;
        }
        
        // Crear la nueva categoria
        return new ServidorDatosCSV(nombreCategoria, usuario, datos);
    }

    /**
     * @see Servicios.Datos#agregarUsuario(Servicios.Usuario) 
     */
    @Override
    public boolean agregarUsuario(Usuario usuario) {
        // Buscar que el usuario no exista
        for (int i = 0; i < usuarios.obtenerCantidadLineas(); i++) {
            String[] linea = usuarios.obtenerLinea(i);
            if( linea[idxUsuario_Usuario].equals( usuario.obtenerUsuario() ) )
                return false;
        }
        
        int campos = 4;
        String[] datosUsuario = new String[campos];
        
        datosUsuario[idxNombres_Usuario] = usuario.obtenerNombres();
        datosUsuario[idxApellidos_Usuario] = usuario.obtenerApellidos();
        datosUsuario[idxUsuario_Usuario] = usuario.obtenerUsuario();
        datosUsuario[idxContrasena_Usuario] = usuario.obtenerContrasena();
        usuarios.agregarLinea(datosUsuario);
        usuarios.guardarCambios();
        
        return true;
    }

    /**
     * Devuelve las categorias registradas para el usuario dado.
     * @see Servicios.Datos#obtenerCategorias(Servicios.Usuario) 
     */
    @Override
    public iServidor[] obtenerCategorias(Usuario usuario) {
        // Validar primero al usuario
        if( !validarUsuario(usuario) )
            return null;
        
        
        
        // Buscar las categorias de servicios que tiene el usuario
        HashSet<String> categoriasUsuario = new HashSet<String>();
        
        /* Agregar categorias por default */
        categoriasUsuario.addAll( categoriasDefault.keySet() );
        
        /* Buscar por usuario */
        Integer[] lineas = datos.buscarLineas( 
                ConstantesCSV.nombreCampos[ConstantesCSV.idxUsuario],
                usuario.obtenerUsuario() );
        
        for (Integer idxLinea : lineas) {
            String[] linea = datos.obtenerLinea(idxLinea);
            categoriasUsuario.add( linea[ConstantesCSV.idxCategoria] );
        }
        
        // Crear el arreglo de servidores
        ArrayList<iServidor> servidores = new ArrayList<iServidor>();
        for (String categoria : categoriasUsuario) {
            servidores.add( new ServidorDatosCSV( categoria,
                    usuario, datos) );
        }
        
        return servidores.toArray( new iServidor[0] );
    }

    @Override
    public boolean cambiarContrasenaUsuario(Usuario usuario, String nuevaContrasena) {
        // Validar al usuario
        if( !validarUsuario(usuario) )
            return false;
        
        // Cambiar la contrasena por la nueva
        for (int i = 0; i < usuarios.obtenerCantidadLineas(); i++) {
            String[] linea = usuarios.obtenerLinea(i);
            String usuarioArchivo = linea[idxUsuario_Usuario];
            if( usuarioArchivo.equals(usuario.obtenerUsuario()) ){
                // Usuario encontrado
                Usuario usuarioNuevo = new Usuario(usuario.obtenerUsuario(),
                         nuevaContrasena);
                usuarioNuevo.encriptar();
                
                linea[idxContrasena_Usuario] = usuarioNuevo.obtenerContrasena();
                usuarios.modificarLinea(linea, i);
                return true;
            }
        }
        
        return false;
    }

    
    
    /**
     * @see Servicios.Datos#validarUsuario(Servicios.Usuario) 
     */
    @Override
    public boolean validarUsuario(Usuario usuario) {
        // Validar referencia
        if( usuario == null )
            return false;
        
        // Buscar al usuario entre los registrados
        /*
        for (int i = 0; i < usuarios.obtenerCantidadLineas(); i++) {
            String[] linea = usuarios.obtenerLinea(i);
            if( linea[idxUsuario_Usuario].equals(usuario.obtenerUsuario()) )
                if( linea[idxContrasena_Usuario].equals(usuario.obtenerContrasena()) )
                    return true;
        }
        //*/
        
        for (int i = 0; i < usuarios.obtenerCantidadLineas(); i++) {
            String[] linea = usuarios.obtenerLinea(i);
            String archivoUsuario = linea[idxUsuario_Usuario];
            if( archivoUsuario.equals(usuario.obtenerUsuario()) ){
                String archivoPass = linea[idxContrasena_Usuario];
                if( usuario.validar(archivoUsuario, archivoPass) )
                    return true;
            }
        }
        
        return false;
    }
    
}
